home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 2.iso
/
STUTTGART
/
LANG
/
C
/
LIB
/
UNIXLIB37B
/
!UnixLib37
/
src
/
time
/
c
/
setitmr
< prev
next >
Wrap
Text File
|
1996-11-09
|
4KB
|
151 lines
/****************************************************************************
*
* $Source: /unixb/home/unixlib/source/unixlib37/src/time/c/RCS/setitmr,v $
* $Date: 1996/10/30 21:59:01 $
* $Revision: 1.3 $
* $State: Rel $
* $Author: unixlib $
*
* $Log: setitmr,v $
* Revision 1.3 1996/10/30 21:59:01 unixlib
* Massive changes made by Nick Burret and Peter Burwood.
*
* Revision 1.2 1996/05/06 09:01:35 unixlib
* Updates to sources made by Nick Burrett, Peter Burwood and Simon Callan.
* Saved for 3.7a release.
*
* Revision 1.1 1996/04/19 21:35:00 simon
* Initial revision
*
***************************************************************************/
static const char rcs_id[] = "$Id: setitmr,v 1.3 1996/10/30 21:59:01 unixlib Rel $";
#include <stddef.h>
#include <errno.h>
#include <sys/os.h>
#include <sys/swis.h>
#include <sys/time.h>
#include <sys/unix.h>
#include <sys/syslib.h>
/* setitimer provides a mechanism for a process to interrupt itself at
some future time. This is achieved by setting a timer; when the
timer expires, the process receives a signal.
Each process has three independent interval timers available:
ITIMER_REAL: A real-time timer that counts clock time. This timer
sends a SIGALRM signal to the process when it expires.
ITIMER_VIRTUAL: A virtual timer that counts CPU time used by the
process. This timer sends a SIGVTALRM signal to the process when it
expires.
ITIMER_PROF: A profiling timer that counts both CPU time used by
the process, and CPU time spent in systems calls on behalf of the
process. This timer sends a SIGPROF signal to the process when it
expires.
Only one timer of each kind can be set at any given time. If a timer
is set that has not yet expired, that timer is reset to the new value.
The setitimer function sets the timer specified by WHICH
according to NEW. The WHICH argument can have a value of
ITIMER_REAL, ITIMER_VIRTUAL, or ITIMER_PROF.
If OLD is not a null pointer, setitimer returns information
about any previous unexpired timer of the same kind in the
structure it points to.
The return value is 0 on success and -1 on failure. */
typedef void (*ticker) (void);
static void
remove_ticker (ticker address, struct timeval *old)
{
int regs[10];
regs[0] = (int) address;
regs[1] = (int) old;
os_swi (OS_RemoveTickerEvent, regs);
}
static int
add_ticker (struct timeval *time, ticker address, struct timeval *new)
{
int regs[10];
regs[0] = (int) (time->tv_sec * 100) + time->tv_usec;
regs[1] = (int) address;
regs[2] = (int) new;
return os_swi (OS_CallAfter, regs) ? -1 : 0;
}
static int
check_ticker (struct timeval *time)
{
if (time->tv_sec > 0 || time->tv_usec > 0)
return 1;
if (time->tv_sec == 0 && time->tv_usec == 0)
return 2;
return 0;
}
struct timer_control
{
ticker callback;
int *sema;
};
static struct timer_control timer_controls[__MAX_ITIMERS] =
{
{__h_sigalrm_init, &__h_sigalrm_sema}, /* ITIMER_REAL */
{__h_sigvtalrm_init, &__h_sigvtalrm_sema}, /* ITIMER_VIRTUAL */
{__h_sigprof_init, &__h_sigprof_sema} /* ITIMER_PROF */
};
int
setitimer (enum __itimer_which which, struct itimerval *new_timer,
struct itimerval *old_timer)
{
struct itimerval *itimer;
/* We can't implement interval timers whilst executing in a task
window. */
if (__taskwindow)
{
errno = ENOSYS;
return -1;
}
if ((unsigned)which >= __MAX_ITIMERS)
{
errno = EINVAL;
return -1;
}
/* __u is current process <sys/unix.h>. */
itimer = &__u->itimers[which];
if (old_timer)
*old_timer = *itimer;
/* Only if a timer is already active (it_value > 0), then remove it */
if ((check_ticker (&itimer->it_value) == 1)
|| check_ticker (&itimer->it_interval))
{
remove_ticker (timer_controls[which].callback, &itimer->it_interval);
*(timer_controls[which].sema) = 0;
}
*itimer = *new_timer;
if (check_ticker (&new_timer->it_value) == 1)
return add_ticker (&new_timer->it_value,
timer_controls[which].callback,
&itimer->it_interval);
return 0;
}